#include "string.h"

#include "usart.h"

#include "ctrl_protocol.h"
#include "ctrl_crc16.h"
#include "oslib.h"

uint8_t wifi_conf_flag = 0;
// extern osMessageQueueId_t UART2_RxQueue;
extern osSemaphoreId_t UART2_RxSema; 
extern char UART2_TaskBuffer[RxBufferSize];
extern osMessageQueueId_t CtrlRecvQueueHandle;

static char RecvTaskBuffer[RxBufferSize];
/**
 * @brief 接收任务, 接收到字符后进入状态机处理成完整的CtrlProt报文
 * 
 * @param argument 未使用
 */
void _RecvTask(void *argument)
{
    uint8_t ch;
    ctrl_prot_t *ptr;

    for (;;)
    {
        // osMessageQueueGet(UART2_RxQueue, &ch, NULL, osWaitForever);
        // if (wifi_conf_flag)
        //     OSLIB_Uart_SendData(&huart_major, &ch, 1);
        // ptr = ctrl_recv_char_to_pack(ch);
        // if (ptr != NULL)
        //     osMessageQueuePut(CtrlRecvQueueHandle, &ptr, NULL, 0);
        osSemaphoreAcquire(UART2_RxSema, osWaitForever);
        memcpy(RecvTaskBuffer, UART2_TaskBuffer, 64);
        if (wifi_conf_flag) {
            OSLIB_Uart_SendData(&huart_major, (const uint8_t *)RecvTaskBuffer, strlen(RecvTaskBuffer));
        }
        ptr = (ctrl_prot_t *)RecvTaskBuffer;
        if (ptr->pre != CTRLPROT_PRE || ptr->src != CTRLPROT_SRC_HOST)
            continue;
        if (ctrl_crc16((uint8_t *)ptr, 10 + ptr->len) != 0)
            continue;
        osMessageQueuePut(CtrlRecvQueueHandle, &ptr, NULL, 0);
    }
}

/**
 * @brief 数据处理任务, 针对接收到的CtrlProt报文, 进行数据处理
 * 
 * @param argument 未使用
 */
void _DataTask(void *argument)
{
    osStatus_t ret;
    ctrl_prot_t *pack;
    ctrl_prot_data_ack_t *ackp;
    uint32_t rx_ticks;

    for (;;)
    {
        ret = osMessageQueueGet(CtrlRecvQueueHandle, &pack, NULL, 100);
        if (ret == osErrorTimeout)
            HAL_GPIO_TogglePin(LED1_GPIO_Port, LED1_Pin);
        if (ret != osOK)
            continue;
        
        HAL_GPIO_WritePin(LED1_GPIO_Port, LED1_Pin, GPIO_PIN_RESET);
        switch (pack->op)
        {
        case CTRLPROT_OP_HOST_ACK:
            if (pack->len != sizeof(ctrl_prot_data_ack_t))
                break;
            ackp = (ctrl_prot_data_ack_t *)pack->data;
            rx_ticks = osKernelGetTickCount();
            // uprintf("%d\r\n", rx_ticks - ackp->tx_ticks);
            break;
        case CTRLPROT_OP_HOST_POSITION:
            break;
        default:
            break;
        }
    }
}